﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;

using FirstFloor.Documents.Pdf.ColorSpaces;

namespace FirstFloor.Documents.Pdf
{
    /// <summary>
    /// Maintains the graphics state during a page render operation.
    /// </summary>
    internal class GraphicsState
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="GraphicsState"/> class.
        /// </summary>
        public GraphicsState()
        {
            this.Ctm = Matrix.Identity;
            this.LineCap = PenLineCap.Flat;
            this.LineJoin = PenLineJoin.Miter;
            this.LineWidth = 0;
            this.MiterLimit = 10;
            this.NonstrokingColor = DeviceGray.Default.DefaultColor;
            this.NonstrokingColorSpace = DeviceGray.Default;
            this.StrokingColor = DeviceGray.Default.DefaultColor;
            this.StrokingColorSpace = DeviceGray.Default;
            this.Th = 100;

        }
        /// <summary>
        /// Gets or sets the color space for stroking operations.
        /// </summary>
        /// <value>The stroke color space.</value>
        public ColorSpace StrokingColorSpace { get; set; }
        /// <summary>
        /// Gets or sets the color space for nonstroking operations.
        /// </summary>
        /// <value>The nonstroking color space.</value>
        public ColorSpace NonstrokingColorSpace { get; set; }
        /// <summary>
        /// Gets or sets the components of the stroking color.
        /// </summary>
        /// <value>The stroke.</value>
        public double[] StrokingColor { get; set; }
        /// <summary>
        /// Gets or sets the components of the nonstroking color.
        /// </summary>
        /// <value>The fill.</value>
        public double[] NonstrokingColor { get; set; }
        /// <summary>
        /// Gets or sets the character spacing.
        /// </summary>
        /// <value>The text character spacing.</value>
        public double Tc { get; set; }
        /// <summary>
        /// Gets or sets the word spacing.
        /// </summary>
        /// <value>The word spacing.</value>
        public double Tw { get; set; }
        /// <summary>
        /// Gets or sets the horizontal scaling.
        /// </summary>
        /// <value>The horizontal scaling.</value>
        public double Th { get; set; }
        /// <summary>
        /// Gets or sets the leading.
        /// </summary>
        /// <value>The text leading.</value>
        public double Tl { get; set; }
        /// <summary>
        /// Gets or sets the font.
        /// </summary>
        /// <value>The text font.</value>
        public string Tf { get; set; }
        /// <summary>
        /// Gets or sets the size of the font.
        /// </summary>
        /// <value>The size of the text font.</value>
        public double Tfs { get; set; }
        /// <summary>
        /// Gets or sets the text rendering mode.
        /// </summary>
        /// <value>The text rendering mode.</value>
        public int Tmode { get; set; }
        /// <summary>
        /// Gets or sets the text rise.
        /// </summary>
        /// <value>The text rise.</value>
        public double Trise { get; set; }
        /// <summary>
        /// Gets or sets the text knockout.
        /// </summary>
        /// <value>The text knockout.</value>
        public double Tk { get; set; }
        /// <summary>
        /// Gets or sets the text matrix.
        /// </summary>
        /// <value>The text matrix.</value>
        public Matrix Tm { get; set; }
        /// <summary>
        /// Gets or sets the text line matrix.
        /// </summary>
        /// <value>The text line matrix.</value>
        public Matrix Tlm { get; set; }
        /// <summary>
        /// Gets or sets the text rendering matrix.
        /// </summary>
        /// <value>The text rendering matrix.</value>
        public Matrix Trm { get; set; }
        /// <summary>
        /// The current transformation matrix.
        /// </summary>
        /// <value>The CTM.</value>
        public Matrix Ctm { get; set; }
        /// <summary>
        /// The thickness of paths.
        /// </summary>
        /// <value>The width of the line.</value>
        public double LineWidth { get; set; }
        /// <summary>
        /// Specifies the shape of the endpoints for any open path that is stroked.
        /// </summary>
        /// <value>The line cap.</value>
        public PenLineCap LineCap { get; set; }
        /// <summary>
        /// Specifies the shape of joints between connected segments of a stroked path.
        /// </summary>
        /// <value>The line join.</value>
        public PenLineJoin LineJoin { get; set; }
        /// <summary>
        /// The maximum length of mitered line joins for stroked paths
        /// </summary>
        /// <value>The stroke miter limit.</value>
        public double MiterLimit { get; set; }
        /// <summary>
        /// Gets or sets the line dash pattern.
        /// </summary>
        /// <value>The dash pattern.</value>
        public string LineDashPattern { get; set; }
        /// <summary>
        /// Gets or sets the line dash offset.
        /// </summary>
        /// <value>The line dash offset.</value>
        public double LineDashOffset { get; set; }

        /// <summary>
        /// Gets the nonstroking RGB color value.
        /// </summary>
        /// <returns></returns>
        public Color NonstrokingRGBColor
        {
            get
            {
                return DeviceRGB.Default.ToColor(this.NonstrokingColorSpace, this.NonstrokingColor);
            }
        }

        /// <summary>
        /// Gets the stroking RGB color value.
        /// </summary>
        /// <returns></returns>
        public Color StrokingRGBColor
        {
            get
            {
                return DeviceRGB.Default.ToColor(this.StrokingColorSpace, this.StrokingColor);
            }
        }

        /// <summary>
        /// Copies this instance.
        /// </summary>
        /// <returns></returns>
        public GraphicsState Copy()
        {
            return new GraphicsState() {
                StrokingColorSpace = this.StrokingColorSpace,
                StrokingColor = this.StrokingColor,
                NonstrokingColor = this.NonstrokingColor,
                NonstrokingColorSpace = this.NonstrokingColorSpace,
                Tc = this.Tc,
                Tf = this.Tf,
                Tfs = this.Tfs,
                Th = this.Th,
                Tk = this.Tk,
                Tl = this.Tl,
                Tlm = this.Tlm,
                Tm = this.Tm,
                Tmode = this.Tmode,
                Trise = this.Trise,
                Trm = this.Trm,
                Tw = this.Tw
            };
        }
    }
}
